package qualomelhor.gwt.modules.client;

import com.MJC.client.Buffers.SimpleBuffer;
import com.MJC.client.Effects.Blind;
import com.MJC.client.Effects.Fade;
import com.MJC.client.Effects.Slide;
import com.MJC.client.Effects.Blinds.BlindLeft;
import com.MJC.client.Effects.Slides.SlideDown;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

public class ImageSliderWidget extends Composite {

	private final AbsolutePanel container;

	private static final int fps = 74;

	public static enum TipoAnimacao {
		FADE,
		SLIDE,
		BLIND
	};
	private SimplePanel[] matrSimpleP;
	private Image[] matrImages;
	private Fade[] matrFade;
	private Blind[] matrBlind;
	private Slide[] matrSlide;
	private int currentImage;
	private Timer timer;
	private TipoAnimacao tipoAnimacao;
	private SimpleBuffer buffer = new SimpleBuffer();
	private boolean primeiraPassagem;

	public ImageSliderWidget() {
		container = new AbsolutePanel();
		initWidget(container);
	}

	public ImageSliderWidget(Image[] matrImages, TipoAnimacao t) {
		this();
		this.matrSimpleP = new SimplePanel[matrImages.length];
		this.matrImages = matrImages;
		this.tipoAnimacao = t;
		setSize("200px", "200px");
		for (int i = 0; i < matrImages.length; i++) {
			this.matrSimpleP[i] = new SimplePanel();
			this.matrImages[i].setStylePrimaryName("imgAnimation");
			//this.matrImages[i].getElement().getStyle().setZIndex(i);
			this.matrSimpleP[i].getElement().getStyle().setZIndex(i);
			this.matrSimpleP[i].add(this.matrImages[i]);
			container.add(this.matrSimpleP[i], 0, 0);
			//container.add(this.matrImages[i], 0, 0);
		}
	}

	public void setListImages(Image[] matrImages) {
		this.matrImages = matrImages;
		this.matrSimpleP = new SimplePanel[matrImages.length];
		container.clear();
		for (int i = 0; i < matrImages.length; i++) {
			this.matrSimpleP[i] = new SimplePanel();
			this.matrImages[i].setStylePrimaryName("imgAnimation");
			//this.matrImages[i].getElement().getStyle().setZIndex(i);
			this.matrSimpleP[i].getElement().getStyle().setZIndex(i);
			this.matrSimpleP[i].add(this.matrImages[i]);
			container.add(this.matrSimpleP[i], 0, 0);
			//container.add(this.matrImages[i], 0, 0);
		}
	}

	public void addImage(Image img) {
		Image[] matrI = new Image[this.matrImages.length + 1];
		int i = 0;
		for (; i < matrImages.length; i++) {
			matrI[i] = new Image(matrImages[i].getUrl());
			//matrI[i] = matrImages[i];
		}
		matrI[i] = img;
		setListImages(matrI);
	}

	public void iniciaAnimacao() {
		if (matrImages.length > 1) {
			if (tipoAnimacao.equals(TipoAnimacao.FADE)) {
				iniciaRotationFade();
			} else if (tipoAnimacao.equals(TipoAnimacao.SLIDE)) {
				iniciaRotationSlide();
			} else if (tipoAnimacao.equals(TipoAnimacao.BLIND)) {
				iniciaRotationBlind();
			}
		}
	}

	public void stopAnimacao() {
		if (timer != null) {
			timer.cancel();
		}
	}

	public void setTipoAnimacao(TipoAnimacao t) {
		tipoAnimacao = t;
	}

	public Image[] getImages() {
		return matrImages;
	}

	public void setSize(String width, String height) {
		container.setSize(width, height);
		for (int i = 0; i < matrImages.length; i++) {
			matrImages[i].setSize(width, height);
			//matrImages[i].setWidth(width);
			//matrImages[i].setHeight(height);
			//matrImages[i].getElement().getStyle().setWidth(200, Unit.PX);
			//matrImages[i].getElement().getStyle().setHeight(200, Unit.PX);
			matrImages[i].getElement().getStyle().setProperty("clip", "rect(0px,200px,200px,0px)");
		}
	}

	public int getWidth() {
		return container.getOffsetWidth();
	}

	public int getHeight() {
		return container.getOffsetHeight();
	}

	private void iniciaRotationFade() {
		matrFade = new Fade[matrImages.length];
		for (int i = 0; i < matrImages.length; i++) {
			matrFade[i] = new Fade(this.matrImages[i]);
			matrFade[i].setFPS(fps);
			matrFade[i].setTime(4);
			currentImage = i;
		}
		primeiraPassagem = true;
		startRotationFade();
	}

	private void startRotationFade() {
		timer = new Timer(){
			public void run(){
				//System.out.println("Atualizando...currentImage = " + currentImage);
				boolean update = true;
				if (currentImage >= 0) {
					update = matrFade[currentImage].update();
					//System.out.println("Atualizando...currentImage = " + currentImage + ", iniciou = " + matrFade[currentImage].hasStarted() + ", update: " + update);
				}
				checkFadeAtual(update);
			}
		};

		currentImage = matrFade.length - 1;
		alternaZOrder(currentImage);
		matrFade[currentImage].toggle();
		if (!primeiraPassagem) {
			matrFade[currentImage - 1].toggle();
		}
		timer.scheduleRepeating(2000);
	}

	private void checkFadeAtual(boolean update) {		
		if (currentImage < 0) {
			// acabou, reiniciar agora...
			//System.out.println("Fim da animação...");
			timer.cancel();
			primeiraPassagem = false;
			//matrFade[matrFade.length - 1].toggle();
			startRotationFade();
		} else {
			//System.out.println("currentImage = " + currentImage + ", update = " + update);
			if (!update) {
				if (currentImage == 0) {
					//System.out.println("A última imagem terminou a animação...");
					currentImage--;

				} else {
					//System.out.println("Terminou uma animação da imagem " + currentImage + " ... iniciará a próxima...");
					currentImage--;
					alternaZOrder(currentImage);
					matrFade[currentImage].toggle();
					if (currentImage == 0) {
						matrFade[matrFade.length - 1].toggle();
					} else if (!primeiraPassagem) {
						matrFade[currentImage - 1].toggle();
					}
				}
			}
		}
	}

	private void iniciaRotationSlide() {

		if (matrSlide != null) {
			timer.cancel();
			for (int j = 0; j < matrSlide.length; j++) {
				matrSlide[j].stop();
			}
		}

		matrSlide = new Slide[matrImages.length];
		for (int i = 0; i < matrImages.length; i++) {
			matrSlide[i] = new Slide(this.matrImages[i], new SlideDown());
			matrSlide[i].setFPS(fps);
			matrSlide[i].setTime(4);
			currentImage = i;
		}
		primeiraPassagem = true;
		startRotationSlide();
	}

	private void startRotationSlide() {

		timer = new Timer(){
			public void run(){
				//System.out.println("Atualizando...currentImage = " + currentImage);
				if (currentImage >= 0) {
					//System.out.println("Atualizando...currentImage = " + currentImage + ", iniciou = " + matrSlide[currentImage].hasStarted() + ", update: " + matrSlide[currentImage].update());
				}
				checkSlideAtual();
			}
		};

		currentImage = matrSlide.length - 1;
		alternaZOrder(currentImage);
		buffer.attemptToggle(matrSlide[currentImage]);
		if (!primeiraPassagem) {
			buffer.attemptToggle(matrSlide[currentImage - 1]);
		}
		timer.scheduleRepeating(2000);
	}

	private void checkSlideAtual(){
		if (currentImage < 0) {
			// acabou, reiniciar agora...
			//System.out.println("Fim da animação...");
			timer.cancel();
			primeiraPassagem = false;
			startRotationSlide();
		} else {
			if (!matrSlide[currentImage].update()) {
				if (currentImage == 0) {
					//System.out.println("A última imagem terminou a animação...");
					currentImage--;
					
				} else {
					//System.out.println("Terminou uma animação da imagem " + currentImage + " ... iniciará a próxima...");
					currentImage--;
					alternaZOrder(currentImage);
					buffer.attemptToggle(matrSlide[currentImage]);
					if (currentImage == 0) {
						buffer.attemptToggle(matrSlide[matrSlide.length - 1]);
					} else if (!primeiraPassagem) {
						buffer.attemptToggle(matrSlide[currentImage - 1]);
					}
				}
			}
		}
	}

	private void iniciaRotationBlind() {

		if (matrBlind != null) {
			timer.cancel();
			for (int j = 0; j < matrBlind.length; j++) {
				matrBlind[j].stop();
			}
		}

		matrBlind = new Blind[matrImages.length];
		for (int i = 0; i < matrImages.length; i++) {
			matrBlind[i] = new Blind(this.matrSimpleP[i], new BlindLeft());
			matrBlind[i].setFPS(fps);
			matrBlind[i].setTime(4);
			currentImage = i;
		}
		primeiraPassagem = true;
		startRotationBlind();
	}

	
	private void startRotationBlind() {
		timer = new Timer(){
			public void run(){
				//System.out.println("Atualizando...currentImage = " + currentImage);
				if (currentImage >= 0) {
					//System.out.println("Atualizando...currentImage = " + currentImage + ", iniciou = " + matrBlind[currentImage].hasStarted() + ", update: " + matrBlind[currentImage].update());
				}
				checkBlindAtual();
			}
		};

		currentImage = matrBlind.length - 1;
		alternaZOrder(currentImage);
		buffer.attemptToggle(matrBlind[currentImage]);
		if (!primeiraPassagem) {
			buffer.attemptToggle(matrBlind[currentImage - 1]);
		}
		timer.scheduleRepeating(2000);
	}

	private void checkBlindAtual(){
		if (currentImage < 0) {
			// acabou, reiniciar agora...
			//System.out.println("Fim da animação...");
			timer.cancel();
			primeiraPassagem = false;
			startRotationBlind();
		} else {
			if (!matrBlind[currentImage].update()) {
				if (currentImage == 0) {
					//System.out.println("A última imagem terminou a animação...");
					currentImage--;
					
				} else {
					//System.out.println("Terminou uma animação da imagem " + currentImage + " ... iniciará a próxima...");
					currentImage--;
					alternaZOrder(currentImage);
					buffer.attemptToggle(matrBlind[currentImage]);
					if (currentImage == 0) {
						buffer.attemptToggle(matrBlind[matrBlind.length - 1]);
					} else if (!primeiraPassagem) {
						buffer.attemptToggle(matrBlind[currentImage - 1]);
					}
				}
			}
		}
	}

	public void setZOrder(Widget w, int zOrder) {
		for (int i = 0; i < container.getWidgetCount(); i++) {
			if (container.getWidget(i).equals(w)) {
				//System.out.println("z-order: " + w.getElement().getStyle().getZIndex());
				w.getElement().getStyle().setZIndex(zOrder);
			}
		}
	}

	public void alternaZOrder(int imageIndex) {
		int maiorZIndex = 0;
		for (int i = 0; i < matrImages.length; i++) {
			//int zIndex = Integer.parseInt(matrImages[i].getElement().getStyle().getZIndex());
			int zIndex = Integer.parseInt(matrSimpleP[i].getElement().getStyle().getZIndex());
			if (zIndex > maiorZIndex) {
				maiorZIndex = zIndex;
			}
		}

		//matrImages[imageIndex].getElement().getStyle().setZIndex(maiorZIndex + 1);
		matrSimpleP[imageIndex].getElement().getStyle().setZIndex(maiorZIndex + 1);
	}
	
	@Override
	protected void onLoad() {
		super.onLoad();
	}
}